/*
 * @Author: NingJian
 * @Date: 2021-09-16 15:30:26
 * @LastEditTime: 2021-09-17 11:30:00
 * @LastEditors: NingJian
 * @Description:  生成 Homo chip 操作的 block数据
 * @FilePath: /cmodel_r=2^128/homo_block.cc
 *  
 */

#include "homo_block.h"

void HomoBlock::init(CAL_MODE cal_mode)
{
    head.init(cal_mode);
    frames.clear();
    checksum = 0x00;
}
void HomoBlock::add_frame(HomoFrame &frame)
{
    frames.push_back(frame);
}
vector<uint8_t> HomoBlock::get_raw_data(bool is_result)
{
    vector<uint8_t> frames_data;
    for (auto &it : frames)
    {
        vector<uint8_t> f_data = it.get_raw_data();
        frames_data.insert(frames_data.end(), f_data.begin(), f_data.end());
    }
    if(is_result) {
        head.set_prarms(4 + frames_data.size(), frames.size() + 1);
    }else {
        head.set_prarms(4 + frames_data.size(), frames.size());
    }


    vector<uint8_t> result_data = head.get_raw_data();

    result_data.insert(result_data.end(), frames_data.begin(), frames_data.end());

    //calc checksum
    checksum = 0x0000;

    for (int i = 0; i < result_data.size(); i += 2)
    {
        checksum += (result_data[i] + (result_data[i + 1] << 8));
    }

    while ((checksum >> 16) != 0)
    {
        checksum = ((checksum >> 16) + (checksum & 0x0000ffff));
    }

    result_data.push_back(checksum & 0xff);
    result_data.push_back((checksum >> 8) & 0xff);
    result_data.push_back(0x00);
    result_data.push_back(0x00);

    return result_data;
}

vector<uint8_t> HomoBlockHead::get_raw_data()
{
    vector<uint8_t> result;
    result.push_back(length & 0xff);
    result.push_back((length & 0xff00) >> 8);
    result.push_back(cal_mode);
    result.push_back(frame_num);
    return result;
}

void HomoBlockHead::init(CAL_MODE cal_mode)
{
    this->cal_mode = cal_mode;
}
void HomoBlockHead::set_prarms(uint16_t length, uint8_t frame_number)
{
    this->length = length / 2;
    this->frame_num = frame_number;
}
void HomoFrame::init(uint8_t id, OP_CODE opcode, PBitCount pbc, EBitCount ebc, vector<uint8_t> &number_1, vector<uint8_t> &number_2)
{
    head.init(id, opcode, pbc, ebc);
    this->number_1 = number_1;
    this->number_2 = number_2;
}

vector<uint8_t> HomoFrame::get_raw_data()
{
    vector<uint8_t> result = head.get_raw_data();
    result.insert(result.end(), number_1.rbegin(), number_1.rend());
    result.insert(result.end(), number_2.rbegin(), number_2.rend());
    return result;
}

void HomoFrameHead::init(uint8_t id, OP_CODE opcode, PBitCount pbc, EBitCount ebc)
{
    this->id = id;
    this->opcode = opcode;
    this->pbc = pbc;
    this->ebc = ebc;
}
vector<uint8_t> HomoFrameHead::get_raw_data()
{
    vector<uint8_t> result;
    result.push_back(id);
    result.push_back(opcode + (pbc << 4));
    result.push_back(ebc);
    result.push_back(0);

    return result;
}

